#include "iostream"
using namespace std;
#include "map.h"
#include "snake.h"
#include "windows.h"
#include "menu.h"
#include "share.h"
#include "explaination.h"
#include "end1.h"
#include "peak_score.h"
using namespace std;


class ConsoleDoubleBuffer {
private:
    HANDLE buffers[2];       // 双缓冲句柄
    bool activeBufferIndex;  // 当前活动缓冲区索引
    COORD mapSize;           // 地图尺寸 {列数, 行数}

public:
    // 初始化缓冲区(传入二维向量地图)
    ConsoleDoubleBuffer(const vector<vector<char>>& gameMap) {
        // 获取地图尺寸
        mapSize = { static_cast<SHORT>(gameMap[0].size()), 
                   static_cast<SHORT>(gameMap.size() + 1) };

        // 创建双缓冲
        buffers[0] = CreateConsoleScreenBuffer(
            GENERIC_WRITE, FILE_SHARE_WRITE, NULL, 
            CONSOLE_TEXTMODE_BUFFER, NULL);
        buffers[1] = CreateConsoleScreenBuffer(
            GENERIC_WRITE, FILE_SHARE_WRITE, NULL,
            CONSOLE_TEXTMODE_BUFFER, NULL);

        // 设置缓冲区尺寸匹配地图
        SetConsoleScreenBufferSize(buffers[0], mapSize);
        SetConsoleScreenBufferSize(buffers[1], mapSize);
        
        // 隐藏光标
        CONSOLE_CURSOR_INFO cci = { 1, FALSE };
        SetConsoleCursorInfo(buffers[0], &cci);
        SetConsoleCursorInfo(buffers[1], &cci);

        activeBufferIndex = false;
    }

    // 渲染地图到后台缓冲区
    void Render(const vector<vector<char>>& gameMap) {
        HANDLE backBuffer = buffers[!activeBufferIndex];
        
        // 逐行写入字符数据
        COORD startPos = { 0,1 };
        DWORD written;
        string scoreText = "当前每次捕食得分：" + to_string(score_unit) + "    当前移动时间间隔：" + to_string(moveInterval) + "ms    当前分数：" + to_string(score) + "    最高分数：" + to_string(peak_score) + "       ";
        WriteConsoleOutputCharacterA(backBuffer, scoreText.c_str(), scoreText.size(), { 0,0 }, &written);
        for (int y = 0; y < mapSize.Y; ++y) {
            WriteConsoleOutputCharacterA(
                backBuffer,           // 目标缓冲区
                gameMap[y].data(),    // 当前行数据指针
                mapSize.X,            // 每行字符数
                startPos,             // 起始坐标
                &written);
            startPos.Y++;  // 换行
        }

        for (const auto& seg : snake) {
            WriteConsoleOutputCharacterW(backBuffer, L"☭", 1, { (short)seg.x, (short)(seg.y + 1) }, &written);
        }
        WriteConsoleOutputCharacterW(backBuffer, L"❂", 1, { (short)food.x, (short)(food.y + 1) }, &written);

    }

    // 切换显示缓冲区
    void SwapBuffers() {
        activeBufferIndex = !activeBufferIndex;
        SetConsoleActiveScreenBuffer(buffers[activeBufferIndex]);
    }

    ~ConsoleDoubleBuffer() {
        CloseHandle(buffers[0]);
        CloseHandle(buffers[1]);
    }


    void ClearBackBuffer() {
        HANDLE backBuffer = buffers[!activeBufferIndex]; // 获取当前后台缓冲区
        DWORD written;
        COORD origin = {0,0};
        
        // 清空字符内容
        FillConsoleOutputCharacter(backBuffer, ' ', 
            mapSize.X * mapSize.Y, origin, &written);
        
        // 清空颜色属性
        FillConsoleOutputAttribute(backBuffer, 0, 
            mapSize.X * mapSize.Y, origin, &written);
        
        // 重置光标
        SetConsoleCursorPosition(backBuffer, origin);
}

};


    void clearConsole() {
        HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
        CONSOLE_SCREEN_BUFFER_INFO csbi;
        GetConsoleScreenBufferInfo(hConsole, &csbi);
        DWORD written;
        FillConsoleOutputCharacter(hConsole, ' ', csbi.dwSize.X * csbi.dwSize.Y, {0,0}, &written);
        SetConsoleCursorPosition(hConsole, {0,0});
}



ConsoleDoubleBuffer buffer(gameMap);

// void game_clear(){
//     buffer.ClearBackBuffer();    // 清空后台缓冲区[2](@ref) 
// }

void fresh(int fresh_mode){
    switch (fresh_mode){
        case 1:
            buffer.Render(gameMap);  // 渲染地图到后台
            buffer.SwapBuffers();    // 切换显示缓冲区
            break;
        case 2: 
            explaination();
            break;
        case 3:
        {
            welcome_menu();
            break;
        }

        case 4:
        {
            if(score < peak_score) {
                end1();
            }
            else {
                end2();
            }
            break;
        }
        case 5:
        {
            peakscore();
            break;
        }    
    }
}